package edu.usc.cmb.iregulome.dao.impl;

import java.util.LinkedList;
import java.util.List;

import org.apache.log4j.LogManager;
import org.apache.log4j.Logger;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import edu.usc.cmb.iregulome.dao.SampleStudyDAO;
import edu.usc.cmb.iregulome.entity.ChIPseqTableEntity;
import edu.usc.cmb.iregulome.entity.ChipSeqBroadPeaksEntity;
import edu.usc.cmb.iregulome.entity.ChipSeqPeaksEntity;
import edu.usc.cmb.iregulome.entity.Sample;
import edu.usc.cmb.iregulome.entity.SampleAttribute;
import edu.usc.cmb.iregulome.entity.Study;

@Transactional
@Service("sampleStudyDAO")
public class SampleStudyDAOImpl implements SampleStudyDAO {

	@Autowired
	private SessionFactory sessionFactory;

	private final Logger log = LogManager.getLogger(SampleStudyDAOImpl.class);

	public void setSessionFactory(SessionFactory sessionFactory) {
		this.sessionFactory = sessionFactory;
	}

	public SessionFactory getSessionFactory() {
		return sessionFactory;
	}

	@SuppressWarnings("unchecked")
	@Override
	public List<String> fetchStudyIds() {
		String hql = "select s.id from Study s";
		try {
			Session session = sessionFactory.getCurrentSession();
			Query q = session.createQuery(hql);
			return q.list();
		} catch (Exception e) {
			log.error("Fetch study id error HQL: " + hql, e);
		}

		return new LinkedList<String>();
	}

	@SuppressWarnings("unchecked")
	@Override
	public List<ChipSeqPeaksEntity> retrieveChipSeqBySampleId(String sampleId) {

		String hql = "from ChipSeqPeaksEntity chip where chip.id.sampleID = '"
				+ sampleId + "'";
		try {
			Session session = sessionFactory.getCurrentSession();
			Query q = session.createQuery(hql);
			return q.list();
		} catch (Exception e) {
			log.error("Fetch chipseq peak error HQL: " + hql, e);
		}
		return new LinkedList<ChipSeqPeaksEntity>();
	}

	@SuppressWarnings("unchecked")
	@Override
	public List<ChipSeqBroadPeaksEntity> retrieveChipSeqBPeaksBySampleId(
			String sampleId) {
		String hql = "from ChipSeqBroadPeaksEntity chip where chip.id.sampleID = '"
				+ sampleId + "'";
		try {
			Session session = sessionFactory.getCurrentSession();
			Query q = session.createQuery(hql);
			return q.list();
		} catch (Exception e) {
			log.error("Fetch ChipSeqBroadPeaksEntity error HQL: " + hql, e);
		}
		return new LinkedList<ChipSeqBroadPeaksEntity>();
	}

	@SuppressWarnings("unchecked")
	@Override
	public List<Sample> fetchSample(String studyId, Integer taxonid,
			String cellType, String factor) {
		String hql = "from Sample sa where 1=1 ";
		try {
			Session session = sessionFactory.getCurrentSession();
			if (studyId != null && studyId.trim().length() != 0) {
				hql += " and sa.study.id = '" + studyId + "'";
			}
			if (taxonid != null) {
				hql += " and sa.taxonid = " + taxonid;
			}
			if (cellType != null && cellType.trim().length() != 0) {
				hql += " and sa.cellType = '" + cellType + "'";
			}
			if (factor != null && factor.trim().length() != 0) {
				hql += " and sa.factor = '" + factor + "'";
			}
			// return empty list if no filter condition
			if (hql.equals("from Sample sa where 1=1 ")) {
				return new LinkedList<Sample>();
			}
			Query q = session.createQuery(hql);
			return q.list();
		} catch (Exception e) {
			log.error("Fetch sample error HQL: " + hql, e);
		}
		return new LinkedList<Sample>();
	}

	@SuppressWarnings("unchecked")
	@Override
	public List<String> fetchAllCellTypes() {

		String hql = "select distinct sa.cellType from Sample sa";
		try {
			Session session = sessionFactory.getCurrentSession();
			Query q = session.createQuery(hql);
			return q.list();
		} catch (Exception e) {
			log.error("Fetch cell type error HQL: " + hql, e);
		}
		return new LinkedList<String>();
	}

	@SuppressWarnings("unchecked")
	@Override
	public List<String> fetchAllFactors() {

		String hql = "select distinct sa.factor from Sample sa";
		try {
			Session session = sessionFactory.getCurrentSession();
			Query q = session.createQuery(hql);
			return q.list();
		} catch (Exception e) {
			log.error("Fetch factor error HQL: " + hql, e);
		}
		return new LinkedList<String>();
	}

	@SuppressWarnings("unchecked")
	@Override
	public List<String[]> fetchAllStudyIdWithTitle(Integer taxonid) {
		String hql = "select s.id, s.title from Study s";

		try {
			Session session = sessionFactory.getCurrentSession();
			if (taxonid != null) {
				hql = "select distinct s.id, s.title from Study s left outer join s.samples sa where sa.taxonid = "
						+ taxonid;
			}
			Query q = session.createQuery(hql);
			return q.list();
		} catch (Exception e) {
			log.error("Fetch study.id+study.title error HQL: " + hql, e);
		}
		return new LinkedList<String[]>();
	}

	@Override
	public Sample fetchSample(String sampleID) {
		String hql = "from Sample sa where sa.id='" + sampleID + "'";
		try {
			Session session = sessionFactory.getCurrentSession();
			Query q = session.createQuery(hql);
			return (Sample) q.list().get(0);
		} catch (Exception e) {
			log.error("Fetch sample by sample id error HQL: " + hql, e);
		}
		return null;
	}

	@Override
	public Study fetchStudyBySampleID(String sampleID) {
		String hql = "from Sample sa where sa.id='" + sampleID + "'";
		try {
			Session session = sessionFactory.getCurrentSession();
			Query q = session.createQuery(hql);
			return ((Sample) q.list().get(0)).getStudy();
		} catch (Exception e) {
			log.error(
					"Fetch study by sample id error use one-to-one match HQL: "
							+ hql, e);
		}
		return null;
	}

	@Override
	public ChIPseqTableEntity fetchChIPSeqStat(String sampleID) {
		String hql = "from ChIPseqTableEntity cste where cste.sampleID='"
				+ sampleID + "'";
		try {
			Session session = sessionFactory.getCurrentSession();
			Query q = session.createQuery(hql);
			return (ChIPseqTableEntity) q.list().get(0);
		} catch (IndexOutOfBoundsException e) {
			return null;
		} catch (Exception e) {
			log.error("Fetch chipseq by sample id error HQL: " + hql, e);
		}
		return null;
	}

	@SuppressWarnings("unchecked")
	@Override
	public List<SampleAttribute> fetchSampleAttributes(String sampleID) {
		String hql = "from SampleAttribute sa where sa.sample.id='" + sampleID
				+ "'";
		try {
			Session session = sessionFactory.getCurrentSession();
			Query q = session.createQuery(hql);
			return q.list();
		} catch (IndexOutOfBoundsException e) {
			return null;
		} catch (Exception e) {
			log.error("Fetch sample attributes by sample id error HQL: " + hql,
					e);
		}
		return null;
	}

	@Override
	public List<Sample> fetchSamples(List<String> sampleIDList) {
		String hql = "from Sample sa where sa.id in (";
		for (String string : sampleIDList) {
			hql += "'" + string + "',";
		}
		hql+="'none')";
		try {
			Session session = sessionFactory.getCurrentSession();
			Query q = session.createQuery(hql);
			return q.list();
		} catch (Exception e) {
			log.error("Fetch sample by sample id error HQL: " + hql, e);
		}
		return null;
	}

	@Override
	public List<ChIPseqTableEntity> fetchChIPSeqStatList(
			List<String> sampleIDList) {
		String hql = "from ChIPseqTableEntity cste where cste.sampleID='NONE'";
		
		for (String string : sampleIDList) {
			hql+=" or cste.sampleID='"+string+"'";
		}
		
		try {
			Session session = sessionFactory.getCurrentSession();
			Query q = session.createQuery(hql);
			return q.list();
		} catch (IndexOutOfBoundsException e) {
			return null;
		} catch (Exception e) {
			log.error("Fetch chipseq by sample id error HQL: " + hql, e);
		}
		return null;
	}

}
